import { vector3Offset, convertColorFormat, log2ssmapObj } from "../core/common.js";
import global from "../core/global.js";
import { changeShadingModel } from '../core/scene.js'
let Model = {
  materialList: [],
  add(options, cb) {
    let scene = window.viewer.scene;
    let model = new SSmap.Model(options.url);
    let entity = new SSmap.Entity();
    entity.addComponent(model);
    scene.addEntity(entity);
    if (options.id) {
      global.modelList.add(model, options.id);
    } else {
      options.id = global.modelList.add(model);
    }
    if (options.srs) {
      model.srs = options.srs;
    }
    this.transform(options, cb);
    if (!options.unSelected) {
      entity.objectName = "Model";
    }
    entity.tag = options.id;
    model.entity.enabled = options.show || true;
    model.debugBoundingVolume = options.debugBoundingVolume || false; //显示包围盒
    model.geometryError = options.geometryError || 0; //消失时机[0,12](像素)0就是不消失
    if (options.childrenEntity && options.childrenEntity.length > 0) {
      model.readyPromise.then(() => {
        model.entity.travalHierarchy((childrenEntity) => {
          let foundObject = options.childrenEntity.find((obj) => {
            return obj.objectName == childrenEntity.objectName;
          });
          if (foundObject) {
            const id = Model.addNode(childrenEntity);
            const { longitude, latitude, height, zRotation, scaleX, scaleZ } =
              foundObject;
            Model.transform({
              id: id,
              position: { longitude, latitude, height },
              offset: {}, //偏移量初始化
              rotation: { z: zRotation },
              scale: {
                x: scaleX,
                y: scaleX,
                z: scaleZ,
              },
            });
          }
        });
      });
    }
  },
  addNode(entity) {
    const { x, y, z } = entity.transform.position;
    entity.offset = SSmap.Vector3.create(x, -z, y);
    entity.scale = SSmap.Vector3.create(
      entity.transform.scale3D.x,
      entity.transform.scale3D.z,
      entity.transform.scale3D.y
    );
    entity.rotation = entity.transform.rotation;
    const nodeId = global.modelList.add(entity);
    entity.tag = nodeId;
    return nodeId;
  },
  transform(options, cb) {
    let model = global.modelList.get(options.id);
    let position = options.position;
    let rotation = options.rotation;
    let offset = options.offset;

    //位置
    if (!options.srs && position && model.entity) {
      let carto = SSmap.Cartographic.fromDegrees(
        position.longitude,
        position.latitude,
        position.height
      );
      model.transform.cartographic = carto;
    }
    // 偏移
    if (offset) {
      model.offset = SSmap.Vector3.create(
        offset.x || 0,
        offset.y || 0,
        offset.z || 0
      );
    }
    // 旋转
    if (rotation) {
      model.rotation = SSmap.Quaternion.fromEulerAngles(
        rotation.x || 0,
        rotation.y || 0,
        rotation.z || 0
      );
    }
    // 缩放
    if (options.scale) {
      model.scale = SSmap.Vector3.create(
        options.scale.x,
        options.scale.y,
        options.scale.z
      );
    }
    if (!model.entity) {
      const { x, y, z } = model.offset;
      // model.offset = SSmap.Vector3.create(x, -z, y)
      let scale = SSmap.Vector3.create(
        model.scale.x,
        model.scale.z,
        model.scale.y
      );
      if (position) {
        let carto = SSmap.Cartographic.fromDegrees(
          position.longitude,
          position.latitude,
          position.height
        );
        model.transform.cartographic = carto;
      } else {
        model.transform.position = SSmap.Vector3.create(x, z, -y);
      }
      model.transform.scale3D = scale;
      model.transform.rotation = SSmap.Quaternion.fromEulerAngles(
        rotation.x || 0,
        rotation.z || 0,
        rotation.y || 0
      );
    }
    if (typeof cb == "function" || options.location) {
      if (model.readyPromise) {
        let that = this
        model.readyPromise.then(() => {
          // if (options.unlit) changeShadingModel(model)
          if (options.color) {
            that.changeModelColor(options.id, options.color)
          }
          options.location && Model.flyTo(options);
          cb && cb(options.id);
        });
      } else {
        cb && cb(options.id);
      }
    }
  },
  flyTo(options, cb = () => { }) {
    let model = global.modelList.get(options.id);
    if (!model) return;
    let scene = window.viewer.scene;
    let camera = scene.mainCamera;
    let cameraController = camera.cameraController();
    let stack = [];
    let renderer = null;
    stack.push(model.entity ? model.entity : model);
    while (stack.length) {
      let entity = stack.pop();
      if (entity.renderer) {
        renderer = entity.renderer;
        break;
      }
      let children = entity.childEntities;
      for (let i = 0; i < children.size(); i++) {
        stack.push(children.get(i));
      }
    }
    if (renderer) {
      let center = renderer.boundingVolume.center;
      let radius = renderer.boundingVolume.boundingSphere.radius * 2 + 5;
      let carto = center.toCartographic();
      // let height = carto.height;
      // carto.height += height;
      carto.height = Math.abs(carto.height + radius);
      let position = carto.toVector3();
      position = vector3Offset(position, {
        offsetY: -radius,
      });
      cameraController.flyTo(position, 2, 0, -45, 0);
      cb(true);
    } else {
      cb(false);
    }
  },
  show(options) {
    let model = global.modelList.get(options.id);
    model.entity.enabled = options.show || false;
  },
  remove(options) {
    global.modelList.remove(options.id, true);
  },
  _getBoundingVolume(options) {
    let model = global.modelList.get(options.id);
    if (!model) return;
    let stack = [];
    let renderer = null;
    stack.push(model.entity ? model.entity : model);
    while (stack.length) {
      let entity = stack.pop();
      if (entity.renderer) {
        renderer = entity.renderer;
        break;
      }
      let children = entity.childEntities;
      for (let i = 0; i < children.size(); i++) {
        stack.push(children.get(i));
      }
    }
    return renderer.boundingVolume;
  },
  _getModel(options) {
    let model = global.modelList.get(options.id);
    return model;
  },
  isShow(id, cb) {
    let model = global.modelList.get(id);
    const show = model ? model.enabled : false;
    cb(show);
  },
  heightModel(id, isHeight) {
    let model = global.modelList.get(id);
    if (isHeight) {
      model.entity.travalRenderers((render) => {
        this.materialList.push({ id: id, material: render.material });
        render.material.color = SSmap.Color.fromRgb(255, 0, 0, 128);
      });
    } else {
      model.entity.travalRenderers((render) => {
        materiaModel = this.materialList.find((item) => item.id === id);
        render.material.color = materiaModel.material;
      });
    }
  },
  changeModelColor(id, color) {
    let model = global.modelList.get(id);
    model.entity.travalRenderers(function (render) {
      let _color = convertColorFormat(color)
      render.material.color = SSmap.Color.fromRgb(_color.r, _color.g, _color.b, _color.a);
      render.material.opacity = _color.a / 255
    })
  }
};

let UEModel = {
  add(options, cb) {
    console.log('options', options)
    let model = new SSmap.UEModel(options.url)
    let position = options.position;
    let rotation = options.rotation;
    let offset = options.offset;
    let scale = options.scale;
    if (scale) {
      model.scale = SSmap.Vector3.create(scale.x, scale.y, scale.z)
    }
    if (offset) {
      model.offset = SSmap.Vector3.create(offset.x || 0, offset.y || 0, offset.z || 0)
    }
    if (rotation) {
      model.rotation = SSmap.Quaternion.fromEulerAngles(rotation.x || 0, rotation.y || 0, rotation.z || 0)
    }
    let carto = SSmap.Cartographic.fromDegrees(
      position.longitude,
      position.latitude,
      position.height
    );
    model.readyPromise.then(function () {
      if (options.id) {
        global.modelList.add(model, options.id);
      } else {
        options.id = global.modelList.add(model);
      }
      // if (options.unlit) changeShadingModel(model)
      model.tag = options.id;
      model.entity.tag = options.id;
      model.entity.transform.cartographic = carto
      cb && cb(options.id)
    })
  },
}

export { Model, UEModel };
